package jam.components;

import jam.beans.Location;
import jam.beans.LocationInstance;
import jam.beans.Shuttle;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

/**
 * Simulates the movement of all shuttles every 3 seconds along their route - updates their GPS location.
 * 
 * @author Kiren.Rawatlal
 */
@EnableScheduling
public class ShuttleMovementSimulation {

  private static final Logger LOGGER = LoggerFactory.getLogger(ShuttleMovementSimulation.class);

  @Autowired
  ShuttleController shuttleController;

  @Autowired
  ShuttleDB shuttleDB;

  Location a1 = new Location();
  Map<Integer, Location> gautrainRoute = new HashMap<Integer, Location>();
  Map<Integer, Location> roseBankRoute = new HashMap<Integer, Location>();
  Map<Integer, Location> commisionerRoute = new HashMap<Integer, Location>();

  @PostConstruct
  private void loadDummyData() {
    gautrainRoute.put(1, new Location(1, -26.211112, 28.039168)); // 5sim
    gautrainRoute.put(2, new Location(2, -26.207759, 28.038319));
    gautrainRoute.put(3, new Location(3, -26.200713, 28.037374));
    gautrainRoute.put(4, new Location(4, -26.194937, 28.041795));// park station
    gautrainRoute.put(5, new Location(5, -26.196303, 28.037495));
    gautrainRoute.put(6, new Location(6, -26.205391, 28.039683));
    gautrainRoute.put(7, new Location(7, -26.208009, 28.040113));

    roseBankRoute.put(1, new Location(1, -26.211112, 28.039168));// 5sim
    roseBankRoute.put(2, new Location(2, -26.206373, 28.030664));
    roseBankRoute.put(3, new Location(3, -26.190508, 28.027745));
    roseBankRoute.put(4, new Location(4, -26.168248, 28.033496));
    roseBankRoute.put(5, new Location(5, -26.160313, 28.034698));
    roseBankRoute.put(6, new Location(6, -26.147353, 28.043516));// rosebank
    roseBankRoute.put(7, new Location(7, -26.154923, 28.046155));
    roseBankRoute.put(8, new Location(8, -26.164900, 28.047786));
    roseBankRoute.put(9, new Location(9, -26.172295, 28.042808));
    roseBankRoute.put(10, new Location(10, -26.181192, 28.034782));
    roseBankRoute.put(11, new Location(11, -26.195363, 28.028774));
    roseBankRoute.put(12, new Location(12, -26.209649, 28.030877));

    commisionerRoute.put(1, new Location(1, -26.211112, 28.039168));// 5sim
    commisionerRoute.put(2, new Location(2, -26.209438, 28.038761));
    commisionerRoute.put(3, new Location(3, -26.207301, 28.038374));
    commisionerRoute.put(4, new Location(4, -26.205877, 28.036631));// 45 com
    commisionerRoute.put(5, new Location(5, -26.207055, 28.035590));
    commisionerRoute.put(6, new Location(6, -26.209693, 28.035858));
    commisionerRoute.put(7, new Location(7, -26.211387, 28.036459));
  }

  private Map<Integer, Location> getRouteMapForRoute(String id) {
    if (id.equals("1")) {
      return gautrainRoute;
    }
    else if (id.equals("2")) {
      return commisionerRoute;
    } else
      return roseBankRoute;
  }

  @Scheduled(fixedRate = 3000)
  public void incrementLocations() {
    List<Shuttle> shuttles = ShuttleDB.getSbShuttles();
    for (Shuttle shuttle : shuttles) {
      LocationInstance oldLocation = shuttle.getLatestLocation();
      Map<Integer, Location> routeMap = getRouteMapForRoute(shuttle.getLatestLocation().getRouteId());
      int arrayPosition = oldLocation.getLocation().getDummyMetaInfoForSimulation();
      if (arrayPosition == routeMap.size())
        arrayPosition = 0;
      Location l = routeMap.get(arrayPosition + 1);
      synchronized (oldLocation) {
        oldLocation.setLocation(l);
        oldLocation.setTime(new Date());
        if (arrayPosition > routeMap.size() / 2) {
          oldLocation.setEnRoute(false);
        }
        if (arrayPosition == 1) {
          oldLocation.setEnRoute(true);
        }

      }
      LOGGER.info("Updated position of shuttle [{}] to location [{}] and enroute is [{}] {}",
          shuttle.getShuttleName(),
          shuttle.getLatestLocation().getLocation().getDummyMetaInfoForSimulation(),
          shuttle.getLatestLocation().isEnRoute(),
          shuttle.getLatestLocation().getLocation().getLatitude());
    }

  }
}